package com.ruoyi.merchant.service.impl;

import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.merchant.domain.ServiceOrder;
import com.ruoyi.merchant.mapper.ServiceOrderMapper;
import com.ruoyi.merchant.rabbitmq.service.SendMQService;
import com.ruoyi.merchant.service.IServiceOrderService;
import com.ruoyi.merchant.utils.OrderNumberGenerator;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

/**
 * 订单Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-11
 */
@Service
public class ServiceOrderServiceImpl implements IServiceOrderService {
    @Autowired
    private ServiceOrderMapper serviceOrderMapper;
    @Resource
    private SendMQService sendMQService;
    @Autowired
    private RedisService redisService;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public ServiceOrder selectServiceOrderById(Long id) {
        return serviceOrderMapper.selectServiceOrderById(id);
    }

    /**
     * 查询订单列表
     *
     * @param serviceOrder 订单
     * @return 订单
     */
    @Override
    public List<ServiceOrder> selectServiceOrderList(ServiceOrder serviceOrder) {
        return serviceOrderMapper.selectServiceOrderList(serviceOrder);
    }

    /**
     * 新增订单
     *
     * @param serviceOrder 订单
     * @return 结果
     */
    @Override
    public int insertServiceOrder(ServiceOrder serviceOrder) {
        long id = OrderNumberGenerator.generateOrderNumber();
        serviceOrder.setStatus(0l);
        serviceOrder.setId(id);
        int insert = serviceOrderMapper.insertServiceOrder(serviceOrder);
        sendMQService.send(serviceOrder.getId().toString());
        redisService.setCacheObject("order"+id,System.currentTimeMillis());
        return insert;
    }

    /**
     * 修改订单
     *
     * @param serviceOrder 订单
     * @return 结果
     */
    @Override
    public int updateServiceOrder(ServiceOrder serviceOrder) {
        return serviceOrderMapper.updateServiceOrder(serviceOrder);
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteServiceOrderByIds(Long[] ids) {
        return serviceOrderMapper.deleteServiceOrderByIds(ids);
    }

    /**
     * 删除订单信息
     *
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteServiceOrderById(Long id) {
        return serviceOrderMapper.deleteServiceOrderById(id);
    }

    @Override
    public int ordertimeout(Long id) {
        return serviceOrderMapper.ordertimeout(id);
    }
    /**
     * 查询店铺每日的订单量和总收入
     * @param mid 传入的商铺id
     * @param data 传入的当日日期
     */
    @Override
    public Map<String, Object> selectCount1(Long mid, String data) {
        Map<String, Object> map = new HashMap<>();
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        /*
         * 需求：根据不同店铺聚合，店铺内使用日期聚合，最后对日期聚合结果度量(单日的价格)
         * queryBuilder.addAggregation() 聚合度量配置
         * AggregationBuilders.terms() 方法表示使用词条聚合，参数为聚合后桶的名称
         * */
        // 这里是开始分桶和度量
        queryBuilder.addAggregation(AggregationBuilders.terms("by_mid").field("mid")
                //subAggregation() 子聚合
                .subAggregation(AggregationBuilders.dateHistogram("by_order_date").field("useTime").calendarInterval(DateHistogramInterval.DAY).format("yyyy-MM-dd")
                 .subAggregation(AggregationBuilders.sum("total_price").field("price"))
                ));

        /*
         * searchHits:代表查询到的整个结果集
         * searchHits.getSearchHits():代表获取结果集中hits中的文档结果集
         * searchHits.getAggregations(): 代表获取聚合度量结果
         * */
        SearchHits<ServiceOrder> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), ServiceOrder.class, IndexCoordinates.of("ServiceOrder"));
        //获取聚合结果：使用第一层聚合的桶名作为键 聚合结果作为值存到map中
        Aggregations aggregations = (Aggregations) searchHits.getAggregations().aggregations();
        ParsedStringTerms shopAggs = aggregations.get("by_mid");//获取第一层聚合的结果对象
        System.out.println("第一层聚合的结果对象是:"+shopAggs);
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++");


        // 获取聚合的店铺桶集合
        List<? extends Terms.Bucket> shopAggsBuckets = shopAggs.getBuckets();
        System.out.println("店铺桶集合:"+shopAggsBuckets);

        // 遍历店铺桶获取桶中各个店铺数据
        shopAggsBuckets.forEach(shopAggsBucket -> {
            System.out.println("店铺桶集合的店铺id!!!:"+shopAggsBucket.getKey());
            System.out.println("店铺桶集合的每个店铺包含(订单)的数量:"+shopAggsBucket.getDocCount());
            Object key = shopAggsBucket.getKey();
            Long e = Long.valueOf(key.toString());

            //判断店铺是否是指定的店铺,是的话进入指定店铺数据遍历
            if (e == mid){
                ParsedDateHistogram dateAggs = (ParsedDateHistogram) shopAggsBucket.getAggregations().asMap().get("by_order_date");
                List<? extends Histogram.Bucket> dateAggsBuckets = dateAggs.getBuckets();
                System.out.println("日期桶集合:"+dateAggsBuckets);

                //遍历指定店铺桶中日期桶
                dateAggsBuckets.forEach(dateAggsBucket -> {
                    System.out.println("日期桶集合日期:"+dateAggsBucket.getKeyAsString());
                    System.out.println("日期桶集合每日日期的订单数量!!!:"+dateAggsBucket.getDocCount());

                    //判断日期是否是指定的日期,是的话进入指定日期数据遍历
                    if (dateAggsBucket.getKeyAsString().equals(data)){
                        map.put("orderNum",dateAggsBucket.getDocCount());
                    }

                    //获取日期桶中价格度量的结果:
                    ParsedSum sumPriceAggs = (ParsedSum) dateAggsBucket.getAggregations().asMap().get("total_price");
                    System.out.println("日期桶度量每日总价格结果!!!:"+sumPriceAggs.getValue());
                    map.put("total",sumPriceAggs.getValue());
                });
            }
            System.out.println("=================不同店铺结束标识(一层循环)=====================");
        });
        System.out.println("返回的数据map为:"+map);
        return map;
    }


    /**
     * 查询店铺每日的订单量和总收入
     * @param mid 传入的商铺id
     * @param data 传入的当日日期
     */
    @Override
    public Map<Long, Map<String, Object>> selectCount2(Long mid, String data) {
        Map<Long, Map<String, Object>> map = new HashMap<>();

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        /*
         * 需求：根据不同店铺聚合，店铺内使用日期聚合，最后对日期聚合结果度量(单日的价格)
         * queryBuilder.addAggregation() 聚合度量配置
         * AggregationBuilders.terms() 方法表示使用词条聚合，参数为聚合后桶的名称
         * */
        // 这里是开始分桶和度量
        queryBuilder.addAggregation(AggregationBuilders.terms("by_mid").field("mid")
                //subAggregation() 子聚合
                .subAggregation(AggregationBuilders.dateHistogram("by_order_date").field("useTime").calendarInterval(DateHistogramInterval.DAY).format("yyyy-MM-dd")
                        .subAggregation(AggregationBuilders.terms("by_service_type").field("serviceTypeId"))
                        .subAggregation(AggregationBuilders.sum("total_price").field("price"))
                ));

        /*
         * searchHits:代表查询到的整个结果集
         * searchHits.getSearchHits():代表获取结果集中hits中的文档结果集
         * searchHits.getAggregations(): 代表获取聚合度量结果
         * */
        SearchHits<ServiceOrder> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), ServiceOrder.class, IndexCoordinates.of("order"));
        //获取聚合结果：使用第一层聚合的桶名作为键 聚合结果作为值存到map中
        Aggregations aggregations = (Aggregations) searchHits.getAggregations().aggregations();
        ParsedStringTerms shopAggs = aggregations.get("by_mid");//获取第一层聚合的结果对象
        System.out.println("第一层聚合的结果对象是:"+shopAggs);
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++");


        // 获取聚合的店铺桶集合
        List<? extends Terms.Bucket> shopAggsBuckets = shopAggs.getBuckets();
        System.out.println("店铺桶集合:"+shopAggsBuckets);

        // 遍历店铺桶
        shopAggsBuckets.forEach(shopAggsBucket -> {
            System.out.println("店铺桶集合的店铺id!!!:"+shopAggsBucket.getKey());
            System.out.println("店铺桶集合的每个店铺包含(订单)的数量:"+shopAggsBucket.getDocCount());
            Object key = shopAggsBucket.getKey();
            Long e = Long.valueOf(key.toString());

            //判断店铺是否是指定的店铺,是的话进入指定店铺数据遍历
            if (e == mid){
                // 获取聚合的日期桶集合
                ParsedDateHistogram dateAggs = (ParsedDateHistogram) shopAggsBucket.getAggregations().asMap().get("by_order_date");
                List<? extends Histogram.Bucket> dateAggsBuckets = dateAggs.getBuckets();
                System.out.println("日期桶集合:"+dateAggsBuckets);

                // 遍历店铺桶嵌套的日期桶
                dateAggsBuckets.forEach(dateAggsBucket -> {
                    System.out.println("日期桶集合日期:"+dateAggsBucket.getKeyAsString());
                    System.out.println("日期桶集合每日日期的订单数量!!!:"+dateAggsBucket.getDocCount());

                    //判断是否是指定日期
                    if (dateAggsBucket.getKeyAsString().equals(data)){

                        // 获取日期桶中嵌套的服务类型桶
                        ParsedLongTerms serviceAggs = (ParsedLongTerms) dateAggsBucket.getAggregations().asMap().get("by_service_type");
                        List<? extends Terms.Bucket> serviceAggsBuckets = serviceAggs.getBuckets();
                        System.out.println("服务类型桶集合:"+serviceAggsBuckets);
                        serviceAggsBuckets.forEach(serviceAggsBucket -> {
                            System.out.println("服务类型桶中服务类型的id!!!:"+serviceAggsBucket.getKey());
                            System.out.println("服务类型桶中每个服务类型的数量(订单分布)!!!:"+serviceAggsBucket.getDocCount());

                            //将查到的服务类型桶中数据封装到map中返回
                            Long serviceId =Long.valueOf(serviceAggsBucket.getKey().toString());
                            long typeNum = serviceAggsBucket.getDocCount();
                            Map<String,Object> map1 = new HashMap<>();
                            map1.put("typeNum",typeNum);
                            map.put(serviceId,map1);

                            //获取日期桶中价格度量的结果:
                            ParsedSum sumPriceAggs = (ParsedSum) dateAggsBucket.getAggregations().asMap().get("total_price");
                            System.out.println("服务类型桶度量每日该服务类型的总价格结果!!!:"+sumPriceAggs.getValue());

                            //将查到的服务类型桶中数据封装到map中返回
                            double typePrice = sumPriceAggs.getValue();
                            map1.put("typePrice",typePrice);
                            map.put(serviceId,map1);
                        });
                    }

                });
            }
            System.out.println("=================不同店铺结束标识(一层循环)=====================");
        });
        System.out.println("返回的数据map为:"+map);
        return map;
    }
}
